package mining;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Scanner;

public class CsvReader {
	BufferedReader br = null;
	String itemDelimiter = ",";
	String filePath = null;

	public CsvReader(String filePath) {
		try {
			this.br = new BufferedReader(new FileReader(filePath));
		} catch (FileNotFoundException e) {
			System.err.println("Cannot find file.  Terminating.");
			System.exit(-1);
		}
	}
	
	public boolean hasNext() {
		try {
			return this.br.ready();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	// transactions uses names - i.e. a,c,e,f
	public List<String> stringRead() {
		try {
			if (!this.br.ready())
				return null;
			String line = this.br.readLine();
			return new ArrayList<String>(Arrays.asList(line.split(this.itemDelimiter)));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	static List<List<Integer>> cache;
	static int cacheIndex = 0;
	static boolean cacheReady = false;
	
	public List<Integer> read() {
		try {
			if (!this.br.ready()) {
				throw new NoSuchElementException();
			}
			String line = this.br.readLine();
			Scanner scanner = new Scanner(line);
			scanner.useDelimiter(this.itemDelimiter);
			List<Integer> transaction = new ArrayList<Integer>();
				while (scanner.hasNextInt())
					transaction.add(scanner.nextInt());
			return Collections.unmodifiableList(transaction);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * returns one transaction from the database, with those items that 
	 * corresponding to the indexes of set bits in <tt>ignoreThese</tt>
	 * removed
	 */
	public List<Integer> readIgnore(BitSet ignoreThese) {
		try {
			if (!this.br.ready()) {
				throw new NoSuchElementException();
			}
			String line = this.br.readLine();
			Scanner scanner = new Scanner(line);
			scanner.useDelimiter(this.itemDelimiter);
			List<Integer> transaction = new ArrayList<Integer>();
				while (scanner.hasNextInt()) 
				{
					int item = scanner.nextInt();
					if (!ignoreThese.get(item)) {
						transaction.add(item);
					}
				}
			return Collections.unmodifiableList(transaction);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public List<Integer> read(int[] actualToConverted) {
		try {
			if (!this.br.ready()) {
				throw new NoSuchElementException();
			}
			String line = this.br.readLine();
			Scanner scanner = new Scanner(line);
			scanner.useDelimiter(this.itemDelimiter);
			List<Integer> transaction = new ArrayList<Integer>();
				while (scanner.hasNextInt()) {
					int converted = actualToConverted[scanner.nextInt()];
					if (converted != -1) {
						transaction.add(converted);
					}
				}
			return Collections.unmodifiableList(transaction);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
//	public Set<Integer> readAsSet(int[] actualToConverted) {
//		try {
//			if (!this.br.ready()) {
//				throw new NoSuchElementException();
//			}
//			String line = this.br.readLine();
//			Scanner scanner = new Scanner(line);
//			scanner.useDelimiter(CsvReader.itemDelimiter);
//			Set<Integer> transaction = new HashSet<Integer>();
//				while (scanner.hasNextInt()) {
//					int converted = actualToConverted[scanner.nextInt()];
//					if (converted != -1) {
//						transaction.add(converted);
//					}
//				}
//			return Collections.unmodifiableSet(transaction);
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
//		return null;
//	}

//	public BitSet readBitSet(int[] actualToConverted) {
//		try {
//			if (!this.br.ready()) {
//				throw new NoSuchElementException();
//			}
//			BitSet transaction = new BitSet();
//			String line = this.br.readLine();
//			Scanner scanner = new Scanner(line);
//			scanner.useDelimiter(CsvReader.itemDelimiter);
//			while (scanner.hasNextInt()) {
//				int converted = actualToConverted[scanner.nextInt()];
//				if (converted != -1) {
//					transaction.set(converted);
//				}
//			}
//			return transaction;
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
//		return null;
//	}

//	public Itemset readItemset() {
//		try {
//			if (!this.br.ready()) {
//				throw new NoSuchElementException();
//			}
//			Itemset itemset = Itemset.newEmptyItemset();
//			String line = this.br.readLine();
//			Scanner scanner = new Scanner(line);
//			scanner.useDelimiter(CsvReader.itemDelimiter);
//			while (scanner.hasNextInt())
//				itemset.set(scanner.nextInt(), true);
//			return itemset;
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
//		return null;
//	}
	
	public BitSet readBitSet() {
		try {
			if (!this.br.ready()) {
				throw new NoSuchElementException();
			}
			BitSet transaction = new BitSet();
			String line = this.br.readLine();
			Scanner scanner = new Scanner(line);
			scanner.useDelimiter(this.itemDelimiter);
			while (scanner.hasNextInt())
				transaction.set(scanner.nextInt());
			return transaction;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public String getItemDelimiter()
	{
		return this.itemDelimiter;
	}

	public void setItemDelimiter(String itemDelimiter)
	{
		this.itemDelimiter = itemDelimiter;
	}

	public String getFilePath()
	{
		return this.filePath;
	}

	public void setFilePath(String filePath) {
		this.filePath = filePath;
	}

}
